
#include "Scorer.h"
#include "PriorityComparator.cpp"
#include <algorithm>
#include <cstdio>

using namespace std;

class PriorityScorer : public Scorer {
    public:
        int get_area_range(vector<Node*> leafs) {
            int smallest = 0;
            int biggest = 0;
            for(int i = 0; i < leafs.size(); i++) {
                int area = leafs.at(i)->get_image()->get_area();
                if(area < smallest) {
                    smallest = area;
                }
                if(area > biggest) {
                    biggest = area;
                }
            }
            return biggest - smallest;
        }
        /*virtual double score(Node* root) {
            vector<Node*> leafs;
            root->get_leafs(&leafs);
            int area_range = get_area_range(leafs);
            double filled_area = root->sum_filled_area(alpha, beta);
            double filled_ratio = filled_area / root->get_area(alpha, beta);
            double area = width * height;
            double root_area = root->get_area(alpha, beta);
            double covered_ratio = root_area / area;
            //return (1 / (double)area_range) * filled_ratio * covered_ratio; 
            double score = (filled_ratio * covered_ratio) / (double)area_range;
//            printf("%.2f %d %.2f %.2f %.2f %.2f\n", score, area_range, filled_ratio, covered_ratio, root_area, area);
            return score;
        }*/

                virtual double score(Node* root) {
            vector<Node*> leafs;
            root->get_leafs(&leafs);
            double sum_areas = 0.0;
            for(int i = 0; i < leafs.size(); i++)
                sum_areas += leafs.at(i)->get_image()->get_area();
            double area = width * height;
            double pbb_area = root->get_area(alpha, beta);
            double e_sum = root->sum_relative_areas(); //priorities
            double total_relative_area = 0.0;
            map<Node*, double> relative_areas;
            for(int i = 0; i < leafs.size(); i++) {
                double relative_area = 1 / leafs.at(i)->get_image()->get_relative_area();
                total_relative_area += relative_area;
                relative_areas.insert(pair<Node*, double>(leafs.at(i), relative_area));
            }
            double score = 0.0;
            sort(leafs.begin(), leafs.end(), PriorityComparator());
            for(int i = 0; i < leafs.size(); i++) {
                double relative_proportion = relative_areas.at(leafs.at(i)) / total_relative_area;
                double ideal_area = relative_proportion * pbb_area;
                double ideal_width = sqrt(ideal_area / leafs.at(i)->get_image()->get_aspect_ratio());
                double individual_score = min((double)leafs.at(i)->get_image()->get_width(), ideal_width) / max((double)leafs.at(i)->get_image()->get_width(), ideal_width);
//                double individual_score = min((double)leafs.at(i)->get_image()->get_area(), ideal_area) / max((double)leafs.at(i)->get_image()->get_area(), ideal_area);
//                if(individual_score > 0.5)
                    score += individual_score;
            }
            double covered_area = min(pbb_area, area) / max(pbb_area, area);
            double filled_area = root->sum_filled_area(alpha, beta);
            double cover_score = min(filled_area, area) / max(filled_area, area);
            return score * cover_score;// * covered_area;
        }
};
